
/**
* The Core class provides functionalities and tools to the client side.
*@author Willy Gardiol <willy@gardiol.org>
*@version 1.0
*@class Core
*#todo Improve translations somehow (maybe use a ajax query?)
*/
var Core={
		ObjectTypes:{}, // Types, to execute JS code on refresh as required
		EnginePath:"", // path to buld the query URL
		k:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", // For base64/UTF decoding
		DumpLoop:0, // For dump to prevent recursion
		Callbacks:{},
		StorageCache:{}
};
/**
* Convert any object to a string. Detects and prevents recursive loops.
*@param mixed Anything to convert to string
*@return string
*/
Core.Dump = function(a){
	var r="",x;
	if ((Core.DumpLoop++)>10){return "DUMP_RECURSION";}
	if((typeof(a)=="object")||(typeof(a)=="array")){
		for(x in a)r+=x+": "+Core.Dump(a[x])+", ";
		a="{"+r+"}";
	}
	Core.DumpLoop--;
	return a;
};
/**
* Execute the callbacks to build any oject on screen that has not been yet initialized.
* This is called onready and after any HtmlRequest. You must call manually when creating some manually.
*/
Core.Refresh = function(){
	var i;
	for ( i in Core.ObjectTypes ){
		$(i).each( function(){
			var init = $(this).data("initialization_done");
			if ( !init ){
				init = {};
			}
			if ( !init[i] ){
				this.tmp_func = Core.ObjectTypes[i];
				this.tmp_func();
				this.tmp_func = null;
				init[i] = true;
				$(this).data("initialization_done", init);
			}
		});
	}
};
/**
* Keep the current user logged in.
*/
Core.keepAlive = function(){
	setInterval( "Core.Request({id:'CoreKeepAlive',type:'json'})" , 60*1000*30); 
	// set to 30 minutes
};

/* DO WE REALLY NEED THESE TWO?
Core.Encode64 = function(i){
	var o="",c1,c2,c3,e1,e2,e3,e4,x=0,k=Core.k;
	i=Core.EncodeUTF8(i);
	while(x<i.length){
		c1=i.charCodeAt(x++);c2=i.charCodeAt(x++);c3=i.charCodeAt(x++);
		e1=c1>>2;e2=((c1&3)<<4)|(c2>>4);e3=((c2&15)<<2)|(c3>>6);e4=c3&63;
		if(isNaN(c2)){e3=e4=64;}else if(isNaN(c3)){e4=64;}
		o=o+k.charAt(e1)+k.charAt(e2)+k.charAt(e3)+k.charAt(e4);
	}
	return o;
};
Core.EncodeUTF8 = function(s){
	var ut="",c,n;
	s=s.replace(/\r\n/g,"\n");
	for(n=0;n<s.length;n++){
		c=s.charCodeAt(n);
		if(c<128){ut+=String.fromCharCode(c);}
		else if((c>127)&&(c<2048)){
			ut+=String.fromCharCode((c>>6)|192);
			ut+=String.fromCharCode((c&63)|128);
		}
		else{
			ut+=String.fromCharCode((c>>12)|224);
			ut+=String.fromCharCode(((c>>6)&63)|128);
			ut+=String.fromCharCode((c&63)|128);
		}
	}
	return ut;
};
*/
/**
* Decode a string from base64 format.
*@param string i The string to translate
*@return string
*/
Core.Decode64 = function (i){
	var o="",c1,c2,c3,e1,e2,e3,e4,x=0,k=Core.k;
	i=i.replace(/[^A-Za-z0-9\+\/\=]/g,"");
	while(x<i.length){
		e1=k.indexOf(i.charAt(x++));e2=k.indexOf(i.charAt(x++));
		e3=k.indexOf(i.charAt(x++));e4=k.indexOf(i.charAt(x++));
		c1=(e1<<2)|(e2>>4);c2=((e2&15)<<4)|(e3>>2);c3=((e3&3)<<6)|e4;
		o=o+String.fromCharCode(c1);
		if(e3!=64){o=o+String.fromCharCode(c2);}
		if(e4!=64){o=o+String.fromCharCode(c3);}
	}
	return Core.DecodeUTF8(o);
};
/**
* Decode a string from UTF8 format.
*@param string ut The string to translate
*@return string
*/
Core.DecodeUTF8 = function(ut){
	var s="",i=0,c=0,c1=0,c2=0;
	while(i<ut.length){
		c=ut.charCodeAt(i);
		if(c<128){s+=String.fromCharCode(c);i++;}
		else if((c>191)&&(c<224)){
			c2=ut.charCodeAt(i+1);s+=String.fromCharCode(((c&31)<<6)|(c2&63));i+=2;
		}
		else {
			c2=ut.charCodeAt(i+1);c3=ut.charCodeAt(i+2);
			s+=String.fromCharCode(((c&15)<<12)|((c2&63)<<6)|(c3&63));
			i+=3;
		}
	}
	return s;
};
/**
* Perform an AJAX request with error control and data formatting.
*@param object o Format is: {mode: get|post, data:{}, type:html|json, cb:callback on success}
*/
Core.Request= function(o,c){
	var ProcessError = function( XMLHttpRequest, textStatus, error ){
			alert("Core.Request '"+o.id+"'  error("+textStatus+"): "+XMLHttpRequest.responseText)
		},
		ProcessSuccess = function(data, textStatus, XMLHttpRequest){
			if(c&&c.cb){
				c.me.tmp_func = c.cb;
				c.me.tmp_func(c.data,data);
				c.me.tmp_func = null;
			}
		};
	jQuery.ajax({	type: o.mode ? o.mode : "GET",
				url: Core.EnginePath + "request.php?RQST="+o.id,
				data: o.data ? o.data : {},
				dataType: o.type,
				cache:false,
				success: ProcessSuccess,
				error: ProcessError
			});
};
/**
* Set a cookie
*/
Core.CookieSet = function(n,v,ed,em,ey){
	var x,s=n+"="+escape(v);
	if(ey){
		x=new Date(ey,em,ed);
		s+="; expires="+x.toGMTString();
	}
	document.cookie=s;
}
/**
* Get a cookie
*/
Core.CookieGet = function(n){
	var r=document.cookie.match('(^|;) ?'+n+'=([^;]*)(;|$)');
	return(r)?(unescape(r[2])):null;
};
/**
* Unset a cookie
*/
Core.CookieDel = function(n){
	var d=new Date();
	d.setTime(d.getTime()-1);
	document.cookie=n+="=; expires="+d.toGMTString();
};
/**
* Read and return storage data sets info
*/
Core.Storage = function(path, callback, force_reload){
	var storePathInfo = function( data, path_info ){
			var callback = data.callback,
				path = data.path;
			Core.StorageCache[data.path] = Core.Fix64(path_info).data.item;
			if ( data.cb ){
				data.cb.cb( Core.StorageCache[data.path], data.cb.data );
			}
		};

	if ( !Core.StorageCache[path] || force_reload ){
		Core.Request({'id':"MgmStorage",'data':{action:"get",path:path},type:"json",mode:"post"},
					{data:{cb:callback,path:path},
					 me:$(this),
					 cb:storePathInfo});
	}
	else{
		callback.cb( Core.StorageCache[path], callback.data );
	}
};
/**
* Fix an object having base_64 strings
*/
Core.Fix64 = function(a){
		if((typeof(a)=="object")||(typeof(a)=="array")){
			for(x in a){
				a[x] = typeof(a[x])=="string" ? Core.Decode64(a[x]) : Core.Fix64(a[x]);
			}
		}
		return a;
	};

(function($){

// Force the Core.Refresh to be executed onready.
$(document).ready( function(){
	Core.Refresh();
});

$.fn.htmlRequest = function(id,data,custom_event) {
	var hc = function(e,data){
		$(this).html(data);
		Core.Refresh();
		if (e){
			$(this).trigger(e, data);
		}
		return false;
	};
	return this.each( function(){
		Core.Request({'id':id, 'data':data, 'mode':"post",type:"html"},
					{cb:hc,data:custom_event,me:$(this)});
	})
};

$.fn.jsonRequest = function(id,data,custom_event ) {
	var jsc = function(e,d){
		var error = d.error ? Core.Decode64(d.error) : false,
			html = d.html ? Core.Decode64(d.html) : false,
			data = Core.Fix64(d.data);
		if ( (error && html) ){
			alert("(json) Request '"+id+"' error("+error+"): "+html);
		}
		else if ( error ){
			alert("(json) Request '"+id+"' error: "+error);
		}
		$(this).trigger( e, [data, error, html, id]);
		return false;
	};
	return this.each( function(){
		Core.Request({'id':id,'data':data,type:"json",mode:"post"},
					{cb:jsc,data:custom_event,me:$(this)});
	});
};

})(jQuery);

// shorthands for lighter JS code
function d64(d){return Core.Decode64(d)}
